package jp.sourceforge.akjrcp.dropsomething;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;

import jp.sourceforge.akjrcp.akj_betas.Akj_betasPlugin;
import jp.sourceforge.akjrcp.akj_betas.Messages;
import jp.sourceforge.akjrcp.dropsomething.MP3ConvertTabBuilder.MP3ConvertTab.SettingMonitor;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegFLVParser;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegUI;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegUtils;
import jp.sourceforge.akjrcp.ffmpeg.FLVInfomation;
import jp.sourceforge.akjrcp.flvtools.basic.FLVToolsPage;
import jp.sourceforge.akjrcp.flvtools.explorer.FlowPlayerShell;
import jp.sourceforge.akjrcp.util.FFMpegExecuter;
import jp.sourceforge.akjrcp.util.FLVTool2Executer;
import jp.sourceforge.akjrcp.util.FileNameUtils;
import jp.sourceforge.akjrcp.util.FlowPlayerHtml;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;

public class FLVConvertTab extends DropsomethingTab {

	private Composite rootControler;

	private StackLayout stack;

	private FLVConvertTab self;

	private ProgressAndList plist;

	ViewPart view;

	private CCombo videoSize;

	private FFMpegExecuter executer;

	private CCombo audioRate;

	private CCombo videoRate;

	private CCombo videoBitRate;

	private CCombo audioBitRate;

	private CCombo audioChannel;

	private Button flowplayerHtml;

	private Button flowplayerSWF;

	private Button avisynth;

	private Button flvtool2;

	private boolean callFLVTool2;

	private boolean copyFlowPlayerSWF;

	private boolean copyFlowPlayerHTML;

	private boolean exportFLVFile;
	private boolean copySWFHTML;
	private Button swfHtml;

	private void createLabel(Composite composite, String label) {
		Label label1 = new Label(composite, SWT.NULL);
		label1.setText(label);
	}

	public FLVConvertTab(ViewPart view, Composite parent, int style) {
		super(parent, style);
		this.view = view;
		self = this;
		stack = new StackLayout();
		this.setLayout(stack);

		rootControler = new Composite(this, SWT.NULL);
		rootControler.setLayout(new GridLayout(1, false));
		
		Composite controler=new Composite(rootControler,SWT.NULL);
		
		controler.setLayout(new GridLayout(3, false));

		IPreferenceStore store=Akj_betasPlugin.getDefault().getPreferenceStore();
		createLabel(controler, Messages.getString("flvconvert.video_size"));
		videoSize = new CCombo(controler, SWT.NULL);
		videoSize.add("320x240");
		videoSize.add("512x384");
		videoSize.add("512x288");
		videoSize.add("640x480");
		videoSize.setText(store.getString(FLVConvertPage.FLVCONVERT_VIDEO_SIZE));
		createLabel(controler, "");
		
		// video rate
		createLabel(controler, Messages.getString("flvconvert.frame_rate"));
		videoRate = new CCombo(controler, SWT.NULL);
		videoRate.add("30");
		videoRate.add("29.97");
		videoRate.add("25");
		videoRate.add("15");
		videoRate.add("1");
		videoRate.setText(store.getString(FLVConvertPage.FLVCONVERT_VIDEO_RATE));
		createLabel(controler, "fps");
		// video bitrate
		createLabel(controler, Messages.getString("flvconvert.video_bitrate"));
		videoBitRate = new CCombo(controler, SWT.NULL);
		videoBitRate.add("4000");
		videoBitRate.add("3000");
		videoBitRate.add("2000");
		videoBitRate.add("1500");
		videoBitRate.add("1000");
		videoBitRate.add("536");
		videoBitRate.add("500");
		videoBitRate.add("472");
		videoBitRate.add("450");
		videoBitRate.add("400");
		videoBitRate.add("350");
		videoBitRate.add("300");
		videoBitRate.add("280");
		videoBitRate.add("250");
		videoBitRate.setText(store.getString(FLVConvertPage.FLVCONVERT_VIDEO_BITRATE));
		createLabel(controler, "kbps");
		// audio rate
		createLabel(controler, Messages.getString("flvconvert.audio_rate"));
		audioRate = new CCombo(controler, SWT.READ_ONLY);
		audioRate.add("44100");
		audioRate.add("22050");
		audioRate.add("11025");
		audioRate.setText(store.getString(FLVConvertPage.FLVCONVERT_AUDIO_RATE));
		createLabel(controler, "hz");
		// audio bitrate
		createLabel(controler, Messages.getString("flvconvert.audio_bitrate"));
		audioBitRate = new CCombo(controler, SWT.NULL);
		audioBitRate.add("320");
		audioBitRate.add("256");
		audioBitRate.add("192");
		audioBitRate.add("128");
		audioBitRate.add("96");
		audioBitRate.add("64");
		createLabel(controler, "kbps");
		audioBitRate.setText(store.getString(FLVConvertPage.FLVCONVERT_AUDIO_BITRATE));
		// audio stereo
		createLabel(controler, Messages.getString("flvconvert.audio_channel"));
		audioChannel = new CCombo(controler, SWT.READ_ONLY);
		audioChannel.add("1");
		audioChannel.add("2");
		audioChannel.select(store.getInt(FLVConvertPage.FLVCONVERT_AUDIO_CHANNEL)-1);
		createLabel(controler, "(1)Monoral (2)Stereo");
		
		Composite controler2 = new Composite(rootControler, SWT.NONE);
		controler2.setLayout(new GridLayout(2, false));
		
		createLabel(controler2, Messages.getString("flvconvert.export_file_type"));
		Composite typeComposite=new Composite(controler2,SWT.NULL);
		typeComposite.setLayout(new GridLayout(2,true));
		exportFLV = new Button(typeComposite,SWT.RADIO);
		exportFLV.setText(Messages.getString("flvconvert.export_file_type_flv"));
		exportFLV.setSelection(true);
		exportFLV.addSelectionListener(new SelectionAdapter(){
			public void widgetSelected(SelectionEvent e) {
				updateExportSettingButtons();
			}
		});
		
		exportSWF = new Button(typeComposite,SWT.RADIO);
		exportSWF.setText(Messages.getString("flvconvert.export_file_type_swf"));
		exportSWF.addSelectionListener(new SelectionAdapter(){
			public void widgetSelected(SelectionEvent e) {
				updateExportSettingButtons();
			}
		});
		
		avisynth = new Button(controler2, SWT.CHECK);
		avisynth.setText(Messages.getString("flvconvert.use_avisynth"));
		avisynth.setSelection(store.getBoolean(FLVConvertPage.FLVCONVERT_USE_AVISYNTH));
		avisynth.setToolTipText(Messages
				.getString("flvconvert.use_avisynth_tooltip"));
		
		Label dummy1=new Label(controler2,SWT.NULL);
		
		flowplayerHtml = new Button(controler2, SWT.CHECK);
		flowplayerHtml.setText(Messages.getString("flvconvert.copy_html"));
		flowplayerHtml.setSelection(store.getBoolean(FLVConvertPage.FLVCONVERT_FLOWPLAYER_HTML));

		flowplayerSWF = new Button(controler2, SWT.CHECK);
		flowplayerSWF.setText(Messages.getString("flvconvert.copy_swf"));
		flowplayerSWF.setSelection(store.getBoolean(FLVConvertPage.FLVCONVERT_FLOWPLAYER_SWF));

		

		flvtool2 = new Button(controler2, SWT.CHECK);
		flvtool2.setText(Messages.getString("flvconvert.use_flvtool2"));
		flvtool2.setToolTipText(Messages
				.getString("flvconvert.use_flvtool2_tooltip"));
		flvtool2.setSelection(store.getBoolean(FLVConvertPage.FLVCONVERT_USE_FLVTOOL2));
		
		Label dummy2=new Label(controler2,SWT.NULL);
		
		swfHtml = new Button(controler2, SWT.CHECK);
		swfHtml.setText(Messages.getString("flvconvert.copy_swf_html"));
		
		//TODO store swf html.
		updateExportSettingButtons();

		Transfer[] types = new Transfer[] { FileTransfer.getInstance() };

		int operations = DND.DROP_MOVE | DND.DROP_COPY;

		DropTarget target2 = new DropTarget(rootControler, operations);
		target2.setTransfer(types);

		target2.addDropListener(new DropMonitor());

		plist = new ProgressAndList(this, SWT.NONE);
		plist.getSimpleFileList().setInput(view);
		plist.getCancelButton().addSelectionListener(new Cancel());
		
		
		stack.topControl = rootControler;
		
		setCanConvert(true);
		updateStatus();
		PlatformUI.getPreferenceStore().addPropertyChangeListener( new SettingMonitor());
	}
	private boolean cancelling;

	private Button exportSWF;

	private Button exportFLV;
	
	private void updateExportSettingButtons(){
		if(exportSWF.getSelection()){
			flowplayerHtml.setEnabled(false);
			flowplayerSWF.setEnabled(false);
			//avisynth.setEnabled(false);
			flvtool2.setEnabled(false);
			
			swfHtml.setEnabled(true);
		}else{
			flowplayerHtml.setEnabled(true);
			flowplayerSWF.setEnabled(true);
			//avisynth.setEnabled(true);
			flvtool2.setEnabled(true);
			
			swfHtml.setEnabled(false);
		}
	}
	public class Cancel implements SelectionListener{

		

		public void widgetSelected(SelectionEvent e) {
			cancelling=true;
			//executer.cancel();
		}

		public void widgetDefaultSelected(SelectionEvent e) {
			// TODO Auto-generated method stub
			
		}
		
	}
	public class ConvertFile implements Runnable {

		public void run() {
			boolean avsAvailable = FFMpegUtils.isAvisynthAvailable(new File(
					executer.getFfmpegPath()));

			while (true) {
				int size = plist.getSimpleFileList().countFiles();
				if (size == 0 || cancelling) {
					view.getSite().getShell().getDisplay().asyncExec(
							new FinishConvert());
					break;
				}
				File file = plist.getSimpleFileList().getFileList()[0];
				String output = null;
				if(exportFLVFile){
				output=FileNameUtils.getChangedExtensionName(file,
						"flv");
				}else{
					output=FileNameUtils.getChangedExtensionName(file,
					"swf");
				}
				// exec ffmpeg;
				File tmp = null;
				boolean useAvisynth = avsAvailable && executer.isUseAvisynth()
						&& FFMpegUtils.shouldUseAvisynth(file);
				if (useAvisynth) {
					try {
						tmp = File.createTempFile("avs", ".avs");
						FileWriter writer = new FileWriter(tmp);
						writer.write(FFMpegUtils.toAVSScript(file
								.getAbsolutePath()));
						writer.close();
						executer.setInput(tmp);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				} else {
					executer.setInput(file);
				}
				executer.setOutput(new File(output));

				try {

					executer.execute();

				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				if (useAvisynth) {
					boolean result = tmp.delete();
					if (!result) {
						DropsomethingView.log.warn("tmp not deleted:" + tmp);
					}
				}


				if (callFLVTool2 && exportFLVFile) {//flv file only

					String path = Akj_betasPlugin.getDefault()
							.getPreferenceStore().getString(
									FLVToolsPage.FLVTOOL2_PATH);
					DropsomethingView.log.info(path);
					if (path.endsWith("flvtool2.exe")) {
						FLVTool2Executer flvtool2Executer = new FLVTool2Executer(
								path, Akj_betasPlugin.getDefault()
										.getProcessPrinter());
						flvtool2Executer.setInput(new File(output));
						try {
							flvtool2Executer.execute();
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}

				if(exportFLVFile){
				if (copyFlowPlayerSWF) {
					File outputFile = new File(output);
					File outputSWF = new File(outputFile.getParent(),
							"FlowPlayer.swf");
					if (!outputSWF.exists()) {
						// flv
						File flowPlayerFile = new File(FlowPlayerShell.flowPlayerDirPath, "FlowPlayer.swf");
						if (flowPlayerFile.exists()) {
							try {
								
								FileUtils.copyFile(flowPlayerFile,
										outputSWF);
								
								
							} catch (FileNotFoundException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (IOException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
					}
				}
				
				if (copyFlowPlayerHTML) {
					
					File outputFile = new File(output);
					File outputHTML = new File(FileNameUtils.getChangedExtensionName(outputFile,
					"html"));
					
					
					
					
					FlowPlayerHtml fhtml=new FlowPlayerHtml(outputFile.getName(),null);
				
					try {
						FileUtils.writeStringToFile(outputHTML,fhtml.toHTML().replaceAll("\n","\r\n"),"SJIS");
						//sadly commons-io didn't work.
						
					} catch (IOException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
							
				}
				}else{
					if (copySWFHTML) {
						
						File outputFile = new File(output);
						//FLVInfomation info=new FFMpegFLVParser(executer.getFfmpegPath()).parseFile(outputFile);
						File outputHTML = new File(FileNameUtils.getChangedExtensionName(outputFile,
						"html"));
						
						
						
						
						try {
							String baseHtml=IOUtils.toString(this.getClass().getResourceAsStream("/jp/sourceforge/akjrcp/dropsomething/resource/swf.html"));
							
							String replaceHtml=StringUtils.replace(baseHtml, "$swfPath", outputFile.getName());
							replaceHtml=StringUtils.replace(replaceHtml, "$width", ""+executer.getVideoWidth());
							replaceHtml=StringUtils.replace(replaceHtml, "$height", ""+executer.getVideoHeight());
							
							FileUtils.writeStringToFile(outputHTML,replaceHtml);
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					

								
					}
					
				}
				
				// change xxx.
				plist.getSimpleFileList().popFile();

				view.getSite().getShell().getDisplay().asyncExec(
						new UpdateTable());
			}
		}
	}

	/*
	 * public class SettingMonitor implements IPropertyChangeListener{
	 * 
	 * public void propertyChange(PropertyChangeEvent event) {
	 * 
	 * if(event.getProperty().equals(FFMpegPage.FFMPEG_PATH)){ String
	 * ffmpegPath=PlatformUI.getPreferenceStore().getString(FFMpegPage.FFMPEG_PATH);
	 * 
	 * if(!FFMpegUtils.isAvailable(ffmpegPath)){ self.setEnabled(true); }else{
	 * self.setEnabled(false); } } }
	 *  }
	 */

	public class FinishConvert implements Runnable {
		public void run() {
			stack.topControl = rootControler;
			layout();
		}
	}

	public class UpdateTable implements Runnable {
		public void run() {

			plist.getSimpleFileList().refresh(true);
			plist.getSimpleFileList().getTable().select(0);
		}
	}

	public void startConvert() {
		String ffmpegPath = FFMpegUI.getFFmpeg();

		if (!FFMpegUtils.isFFMpegAvailable(ffmpegPath)) {
			return;
		}

		plist.getSimpleFileList().getTable().select(0);

		executer = new FFMpegExecuter(ffmpegPath, Akj_betasPlugin.getDefault()
				.getProcessPrinter());

		executer.setVideoBitrate(Integer.parseInt(videoBitRate.getText()));
		executer.setVideoRate(Double.parseDouble(videoRate.getText()));
		executer.setVideoSize(videoSize.getText());
		executer.setAudioChannel(Integer.parseInt(audioChannel.getText()));
		executer.setAudioBitrate(Integer.parseInt(audioBitRate.getText()));
		executer.setAudioSampleRate(Integer.parseInt(audioRate.getText()));

		executer.setUseAvisynth(avisynth.getSelection());

		callFLVTool2 = flvtool2.getSelection();
		copyFlowPlayerHTML = flowplayerHtml.getSelection();
		copyFlowPlayerSWF = flowplayerSWF.getSelection();

		exportFLVFile=exportFLV.getSelection();
		copySWFHTML=swfHtml.getSelection();
		
		Thread t = new Thread(new ConvertFile());
		t.start();
	}

	public void addDragAndDropFile(String path) {
		if (stack.topControl == rootControler) {
			stack.topControl = plist;
			plist.addFile(path);

			layout();

			// little bit worry
			startConvert();

		} else {
			plist.addFile(path);
			layout();
		}

	}

	public class DropMonitor extends DropTargetAdapter {
		public void dragEnter(DropTargetEvent event) {
			// log.infodrag enter:"+event.data);
		}

		public void dragOver(DropTargetEvent event) {
			// log.infodrag over:"+event.data);
		}

		public void drop(DropTargetEvent event) {
			// log.infodrop:"+event.data);

			// log.info(event.data.getClass().getName());
			String files[] = (String[]) event.data;

			for (int i = 0; i < files.length; i++) {
				addDragAndDropFile(files[i]);
			}

		}
	}

	public Composite createControls(Composite parent) {
		// TODO Auto-generated method stub
		return new Composite(parent,SWT.NULL);
	}

	public void inconvert(File file) {
		// TODO Auto-generated method stub
		
	}

	public void beforeConvert() {
		// TODO Auto-generated method stub
		
	}

	public void afterConvert() {
		// TODO Auto-generated method stub
		
	}

	public void cancelConvert() {
		// TODO Auto-generated method stub
		
	}
	
	public void updateStatus() {
	
		String ffmpegPath=FFMpegUI.getFFmpeg();
		if(ffmpegPath==null){
			setCantConvertStatusbarMessage(Messages.getString("ffmpeg_statusbar.no_ffmpeg"));
			setCanConvert(false);
		}else{
			setCanConvert(true);
		}
		
	}
	public class SettingMonitor implements IPropertyChangeListener {

		public void propertyChange(PropertyChangeEvent event) {
			log.info(event.getProperty());
			if (event.getProperty().equals(FFMpegUI.FFMPEG_PATH)) {
				updateStatus();
			} 
		}
	}

}
